#include "tabla.h"
#include <sstream>
#include <iostream>
#include <vector>

extern std::vector<std::string> Vec_from_string(const std::string& string);

void Tabla::Be_fajl(std::string& elso_sor, std::stringstream& tobbi, const std::fstream& mibol)
{
	_f.close();
	_f.open(_nev.c_str(), std::fstream::in | std::fstream::out);
	std::stringstream tmp;
	tmp << mibol.rdbuf();
	
	std::getline(tmp, elso_sor);
	
	tobbi << tmp.rdbuf();
	
	std::stringstream tobbi2;
	if (!tobbi.good())
	{
		tobbi.clear();
		tobbi.flush();
	}
}

void Tabla::Ki_fajl(const std::string& elso_sor, const std::stringstream& tobbi, std::fstream& hova)
{	
	_f.close();
	_f.open(_nev.c_str(), std::fstream::in | std::fstream::out | std::fstream::trunc);
	
	std::stringstream _elso_sor(elso_sor);
	hova << _elso_sor.rdbuf() << std::endl << tobbi.rdbuf();
	
	_f.close();
	_f.open(_nev.c_str());
}

Tabla::Tabla(const std::string& s) : _nev(s)
{
	_f.open(_nev.c_str(), std::fstream::in | std::fstream::out | std::fstream::trunc);
	_oszlopok_szama = 0;
	_sorok_szama = 0;
}

Tabla::~Tabla()
{
	for (int i = 0; i < _oszlopok.size(); ++i)
	{
		delete _oszlopok[i];
	}
	
	_f.close();
}

void Tabla::Modosit_felvetel(const std::string& nev, const std::string& tip)
{
	std::string tnev;
	if (tip == "logikai")
	{
		Oszlop_log* a = new Oszlop_log(nev);
		_oszlopok.push_back(a);
		tnev = "L";
		tnev += nev;
	}
	else if (tip == "egesz")
	{
		Oszlop_egesz* a = new Oszlop_egesz(nev);
		_oszlopok.push_back(a);
		tnev = "E";
		tnev += nev;
	}
	else if (tip == "valos")
	{
		Oszlop_valos* a = new Oszlop_valos(nev);
		_oszlopok.push_back(a);
		tnev = "V";
		tnev += nev;
	}
	else if (tip == "szoveg")
	{
		Oszlop_szoveg* a = new Oszlop_szoveg(nev);
		_oszlopok.push_back(a);
		tnev = "S";
		tnev += nev;
	}
	
	std::string elso_sor;
	std::stringstream tobbi;
	Be_fajl(elso_sor, tobbi, _f);
	elso_sor += tnev;
	elso_sor += ";";
	Ki_fajl(elso_sor, tobbi, _f);
	
	++_oszlopok_szama;
}

void Tabla::Modosit_felvetel(const std::string& nev, const std::string& tip, const std::string& ertekek)
{
	std::string tnev;
	if (tip == "logikai")
	{
		Oszlop_log* a = new Oszlop_log(nev);
		_oszlopok.push_back(a);
		tnev = "L";
		tnev += nev;
	}
	else if (tip == "egesz")
	{
		Oszlop_egesz* a = new Oszlop_egesz(nev);
		_oszlopok.push_back(a);
		tnev = "E";
		tnev += nev;
	}
	else if (tip == "valos")
	{
		Oszlop_valos* a = new Oszlop_valos(nev);
		_oszlopok.push_back(a);
		tnev = "V";
		tnev += nev;
	}
	else if (tip == "szoveg")
	{
		Oszlop_szoveg* a = new Oszlop_szoveg(nev);
		_oszlopok.push_back(a);
		tnev = "S";
		tnev += nev;
	}
	
	std::vector<std::string> vec = Vec_from_string(ertekek);
	
	for (int i = 0; i < vec.size(); ++i) _oszlopok[_oszlopok.size()-1]->Feltolt(vec[i]);

	std::string elso_sor;
	std::stringstream tobbi;
	Be_fajl(elso_sor, tobbi, _f);
	elso_sor += tnev;
	elso_sor += ";";
	
	std::stringstream tobbi2;
	std::string sor;
	
	int i = 0;
	while (tobbi.good())
	{
		std::getline(tobbi,sor);
		tobbi2 << sor << vec[i] << ";" << std::endl;
		++i;
	}
	
	Ki_fajl(elso_sor, tobbi2, _f);
	
	++_oszlopok_szama;
}

void Tabla::Beszur(const std::string& s)
{
	std::vector<std::string> ertekek;
	std::stringstream ss(s);
	std::string tmp;
	while(std::getline(ss, tmp, ';'))
	{
		ertekek.push_back(tmp);
	}
	
	if (_sorok_szama != 0 && ertekek.size() != _oszlopok_szama) throw SOR_MERETE_NEM_MEGFELELO;
	else
	{	
		std::string _elso_sor;
		std::stringstream _tobbi;
		Be_fajl(_elso_sor, _tobbi, _f);
		
		_tobbi << s << std::endl;
		Ki_fajl(_elso_sor, _tobbi, _f);
		for (int i = 0; i < _oszlopok_szama; ++i) _oszlopok[i]->Feltolt(ertekek[i]);
	}
	++_sorok_szama;
}

std::string Tabla::Listaz()
{
	std::stringstream s;
	
	for (int i = 0; i < _oszlopok.size(); ++i)
	{
		if (_oszlopok[i]->Tipus() == "logikai") s << "L";
		else if (_oszlopok[i]->Tipus() == "egesz") s << "E";
		else if (_oszlopok[i]->Tipus() == "valos") s << "V";
		else if (_oszlopok[i]->Tipus() == "szoveg") s << "S";
		s << _oszlopok[i]->Nev() << ";";
	}
	s << std::endl;
	
	for (int i = 0; i < _sorok_szama; ++i)
	{
		for (int j = 0; j < _oszlopok_szama; ++j)
		{
			std::vector<std::string> v = Vec_from_string(_oszlopok[j]->Ertekek());
			s << v[i] << ";";
		}
		
		s << std::endl;
	}
	
	return s.str();
}

void Tabla::Szurt_listaz(Funktor f, const int& o)
{
	std::stringstream ss(Listaz().c_str());
	std::string sor;
	std::getline(ss, sor);
	
	std::stringstream eredm;
	
	while(ss.good())
	{
		std::getline(ss, sor);
		if (ss.fail()) break;
		std::vector<std::string> vec = Vec_from_string(sor);
		if (f(vec[o])) eredm << sor;
		eredm << std::endl;
	}
	
	std::cout << eredm.str();
}

void Tabla::Torol(Funktor f, const int& o)
{
	std::stringstream ss(Listaz().c_str());
	std::string sor;
	std::string oszlopok;
	std::getline(ss, oszlopok);
	
	int i = 0;
	int c = 0;
	
	std::stringstream eredm;
	eredm << oszlopok << std::endl;
	
	while(i-c < _sorok_szama)
	{
		std::getline(ss,sor);
		if (ss.fail()) break;
		std::vector<std::string> vec = Vec_from_string(sor);
		if (f(vec[o]))
		{
			for (int j = 0; j < _oszlopok_szama; ++j) _oszlopok[j]->Torol(i-c);
			++c;
			--_sorok_szama;
		}
		else eredm << sor << std::endl;
		++i;
	}
	
	_f.close();
	_f.open(_nev.c_str(), std::fstream::in | std::fstream::out | std::fstream::trunc);
	
	_f << eredm.str();
	_f.close();
	_f.open(_nev.c_str());
}

void Tabla::Urit()
{
	int c = 0;
	
	for (int i = 0; i - c < _sorok_szama; ++i)
	{
		for (int j = 0; j < _oszlopok_szama; ++j)
		{
			_oszlopok[j]->Torol(i-c);
		}
		++c;
		--_sorok_szama;
	}
	
	std::stringstream ss(Listaz().c_str());
	std::string oszlopok;
	std::getline(ss, oszlopok);
	
	_f.close();
	_f.open(_nev.c_str(), std::fstream::in | std::fstream::out | std::fstream::trunc);
	
	_f << oszlopok;
	_f.close();
	_f.open(_nev.c_str());
}